import hashlib
from django.core.cache import cache
from django.core.files.uploadhandler import TemporaryFileUploadHandler, MemoryFileUploadHandler, FileUploadHandler
import time
from com.kjssoft.rainbow import LOGGER
from com.kjssoft.rainbow.image.forms import ImageForm

__author__ = 'Sea'


class RainbowImageUploadedProgressHandler(FileUploadHandler):
    def __init__(self, progress_mark, *args, **kwargs):
        super(RainbowImageUploadedProgressHandler, self).__init__(*args, **kwargs)
        self.progress_mark = progress_mark
        self.file_uploaded_progress_mark = None

    def new_file(self, file_name, *args, **kwargs):
        super(RainbowImageUploadedProgressHandler, self).new_file(file_name, *args, **kwargs)
        LOGGER.debug('new file %s content length %s' % (self.file_name, self.content_length))
        md5 = hashlib.md5()
        md5.update(self.file_name)
        md5.update(self.progress_mark)
        self.file_uploaded_progress_mark = md5.hexdigest()
        LOGGER.debug('file uploaded progress mark md5 %s' % self.file_uploaded_progress_mark)
        cache.set(self.file_uploaded_progress_mark, {
            'uploaded_data':0,
            'uploaded_finish':0,
            'content_length':0
        })

    def handle_raw_input(self, input_data, META, content_length, boundary, encoding=None):
        super(RainbowImageUploadedProgressHandler, self).handle_raw_input(input_data, META, content_length, boundary, encoding)
        LOGGER.debug('progress mark %s' % self.progress_mark)
        LOGGER.debug('uploaded image content length %s' % content_length)
        cache.set(self.progress_mark, {
            'uploaded_data':0,
            'uploaded_finish':0,
            'content_length':content_length
        })

    def receive_data_chunk(self, raw_data, start):
        uploaded_progress = cache.get(self.file_uploaded_progress_mark)
        uploaded_progress['uploaded_data'] = start + len(raw_data)
        cache.set(self.file_uploaded_progress_mark, uploaded_progress)
        LOGGER.debug('file receive data length %s' % (uploaded_progress['uploaded_data']))
        time.sleep(0.1)
        return raw_data

    def file_complete(self, file_size):
        LOGGER.debug('file uploaded complete')
        uploaded_progress = cache.get(self.file_uploaded_progress_mark)
        uploaded_progress['uploaded_finish'] = 1
        uploaded_progress['content_length'] = file_size
        cache.set(self.file_uploaded_progress_mark, uploaded_progress)

    def upload_complete(self):
        LOGGER.debug('uploaded complete')
        uploaded_progress = cache.get(self.progress_mark)
        uploaded_progress['uploaded_finish'] = 1
        cache.set(self.progress_mark, uploaded_progress)


class RainbowImageTemporaryFileUploadHandler(TemporaryFileUploadHandler):
    def __init__(self, *args, **kwargs):
        super(RainbowImageTemporaryFileUploadHandler, self).__init__(*args, **kwargs)
        self.content_md5 = None

    def new_file(self, file_name, *args, **kwargs):
        super(RainbowImageTemporaryFileUploadHandler, self).new_file(file_name, *args, **kwargs)
        self.content_md5 = hashlib.md5()

    def receive_data_chunk(self, raw_data, start):
        super(RainbowImageTemporaryFileUploadHandler, self).receive_data_chunk(raw_data, start)
        self.content_md5.update(raw_data)

    def file_complete(self, file_size):
        f = super(RainbowImageTemporaryFileUploadHandler, self).file_complete(file_size)
        f.content_md5 = self.content_md5.hexdigest()
        self.content_md5 = None
        return f

class RainbowImageMemoryFileUploadHandler(MemoryFileUploadHandler):
    def __init__(self, *args, **kwargs):
        super(RainbowImageMemoryFileUploadHandler, self).__init__(*args, **kwargs)
        self.content_md5 = None

    def receive_data_chunk(self, raw_data, start):
        data = super(RainbowImageMemoryFileUploadHandler, self).receive_data_chunk(raw_data, start)
        if self.activated:
            if self.content_md5:
                self.content_md5.update(raw_data)
        else:
            return data

    def new_file(self, *args, **kwargs):
        if self.activated:
            self.content_md5 = hashlib.md5()
        return super(RainbowImageMemoryFileUploadHandler, self).new_file(*args, **kwargs)

    def handle_raw_input(self, input_data, META, content_length, boundary, encoding=None):
        super(RainbowImageMemoryFileUploadHandler, self).handle_raw_input(input_data, META, content_length, boundary, encoding)

    def file_complete(self, file_size):
        if not self.activated:
            return

        f = super(RainbowImageMemoryFileUploadHandler, self).file_complete(file_size)
        if f and self.content_md5:
            f.content_md5 = self.content_md5.hexdigest()
            self.content_md5 = None
        return f


class RainbowImageUploadMiddleware(object):

    def process_request(self, request):
        request_path = request.get_full_path()
        if request_path.__contains__('/rainbow/image/save'):
            request.upload_handlers = [
                RainbowImageMemoryFileUploadHandler(),
                RainbowImageTemporaryFileUploadHandler(),
            ]
            if ImageForm.IMAGE_UPLOADED_PROGRESS_FIELD_NAME in request.GET:
                progress_mark = request.GET.get(ImageForm.IMAGE_UPLOADED_PROGRESS_FIELD_NAME)
                if progress_mark:
                    request.upload_handlers.insert(0, RainbowImageUploadedProgressHandler(progress_mark))